package com.xiaoming.mojbackendjudgeservice;

import cn.hutool.json.JSONUtil;

import com.xiaoming.mojbackendcommon.common.ErrorCode;
import com.xiaoming.mojbackendcommon.exception.BusinessException;
import com.xiaoming.mojbackendjudgeservice.codesandbox.CodeSandBox;
import com.xiaoming.mojbackendjudgeservice.codesandbox.CodeSandBoxFactory;
import com.xiaoming.mojbackendjudgeservice.codesandbox.CodeSandBoxProxy;
import com.xiaoming.mojbackendjudgeservice.strategy.JudgeContext;
import com.xiaoming.mojbackendmodel.model.codesandbox.ExecuteCodeRequest;
import com.xiaoming.mojbackendmodel.model.codesandbox.ExecuteCodeResponse;
import com.xiaoming.mojbackendmodel.model.codesandbox.JudgeInfo;
import com.xiaoming.mojbackendmodel.model.dto.question.JudgeCase;
import com.xiaoming.mojbackendmodel.model.entity.Question;
import com.xiaoming.mojbackendmodel.model.entity.QuestionSubmit;
import com.xiaoming.mojbackendmodel.model.enums.JudgeInfoMessageEnum;
import com.xiaoming.mojbackendmodel.model.enums.QuestionSubmitStatusEnum;
import com.xiaoming.mojbackenserviceclient.client.QuestionClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class JudgeServiceImpl implements JudgeService {
    @Value("${sandbox.type}")
    private String type;

    @Resource
    private QuestionClient questionClient;
    @Resource
    private JudgeManager judgeManager;

    @Override
    public QuestionSubmit doJudge(long questionSubmitId) {
        //1.根据传入id 获取提交信息
        QuestionSubmit questionSubmit=questionClient.getQuestionSubmitById(questionSubmitId);
        if(questionSubmit==null)
        {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"提交信息不存在");
        }
        //根据提交信息获取题目信息
        Question question=questionClient.getQuestionById(questionSubmit.getQuestionId());
        if(question==null)
        {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR,"题目不存在");
        }
        //若题目已经在判题中 抛出异常 避免重复判题
        if(questionSubmit.getStatus().equals( QuestionSubmitStatusEnum.RUNNING))
        {
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"题目" +
                    "正在判题中");
        }

        //2.更改题目提交状态
        System.out.println("更改提交题目状态");
        QuestionSubmit questionSubmitUpdate=new QuestionSubmit();
        questionSubmitUpdate.setStatus(QuestionSubmitStatusEnum.RUNNING.getValue());
        questionSubmitUpdate.setId(questionSubmitId);
        boolean update=questionClient.updateById(questionSubmitUpdate);
        if(!update)
        {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"题目提交状态更新异常");
        }
        System.out.println("更改提交题目状态结束");
        //获取判题用例
        String judgeCase = question.getJudgeCase();
        List<JudgeCase> judgeCaseList = JSONUtil.toList(judgeCase, JudgeCase.class);
        List<String> inputList = judgeCaseList.stream().map(JudgeCase::getInput).collect(Collectors.toList());
        //构造沙箱请求对象
        ExecuteCodeRequest executeCodeRequest=new ExecuteCodeRequest();
        executeCodeRequest.setInputList(inputList);
        executeCodeRequest.setLanguage(questionSubmit.getLanguage());
        executeCodeRequest.setCode(questionSubmit.getCode());

        //3.调用沙箱 获取执行结果
        CodeSandBox codeSandBox= CodeSandBoxFactory.newInstance(type);
        CodeSandBox codeSandBox1= new CodeSandBoxProxy(codeSandBox);
        ExecuteCodeResponse executeCodeResponse = codeSandBox1.executeCode(executeCodeRequest);
        List<String> ouputList =executeCodeResponse.getOutPutList();
        //4.根据执行结果 获取判题状态等信息
        JudgeContext judgeContext=new JudgeContext();
        judgeContext.setJudgeInfo(executeCodeResponse.getJudgeInfo());
        judgeContext.setInputList(inputList);
        judgeContext.setOutputList(ouputList);
        judgeContext.setQuestion(question);
        judgeContext.setJudgeCaseList(judgeCaseList);
        judgeContext.setQuestionSubmit(questionSubmit);


        //5修改数据库中的判题结果
        JudgeInfo judgeInfo = judgeManager.doJudge(judgeContext);
        String message = judgeInfo.getMessage();
        if(message.equals(JudgeInfoMessageEnum.ACCEPTED.getValue()))
        {
            //修改题的提交数 通过数
            question.setAcceptedNum(question.getAcceptedNum()+1);
            question.setSubmitNum(question.getSubmitNum()+1);
        }
        else {
            question.setSubmitNum(question.getSubmitNum()+1);

        }

        update = questionClient.updateQuestionById(question);
        if(!update)
        {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"题目状态更新异常");
        }
        questionSubmitUpdate.setStatus(QuestionSubmitStatusEnum.SUCCEED.getValue());
        questionSubmitUpdate.setId(questionSubmitId);
        questionSubmitUpdate.setJudgeInfo(JSONUtil.toJsonStr(judgeInfo));
        questionSubmitUpdate.setId(questionSubmitId);
        update=questionClient.updateById(questionSubmitUpdate);
        if(!update)
        {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR,"题目提交状态更新异常");
        }
        QuestionSubmit questionSubmitResult=questionClient.getQuestionSubmitById(questionSubmitId);


        return questionSubmitResult;
    }
}
